package com.shakespace.algorithm.linked_list

import kotlin.math.max

/**
 * 给你两个 非空 的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储 一位 数字。
 *
 * 请你将两个数相加，并以相同形式返回一个表示和的链表。
 *
 * 你可以假设除了数字 0 之外，这两个数都不会以 0 开头。
 */

fun main() {

}

fun addTwoNumbers2(node1: ListNode, node2: ListNode): ListNode? {
    // initial the header
    val head = ListNode(0)
    // current
    var latest: ListNode? = null
    // carry for Ten digital
    var carry = 0

    var n1: ListNode? = node1
    var n2: ListNode? = node2
    while (n1 != null || n2 != null) {
        val v1 = n1?.`val` ?: 0
        val v2 = n2?.`val` ?: 0

        // calc
        var result = v1 + v2 + carry
        if (result > 9) {
            carry = 1
            result %= 10
        } else {
            carry = 0
        }
        val t = ListNode(result)
        // set 1st tail , and set the value to current as well
        if (head.next == null) {
            head.next = t
            latest = t
        } else if (latest != null) {
            // move to next
            latest.next = t
            latest = t
        }

        // move to next
        n1 = n1?.next
        n2 = n2?.next
    }

    // check last carry
    if (carry != 0) {
        latest?.next = ListNode(1)
    }
    return head.next
}


/**
 * my solution
 */
fun addTwoNumbers(node1: ListNode, node2: ListNode): ListNode {
    val list1 = listNodeToIntArray(node1)
    val list2 = listNodeToIntArray(node2)

    val size1 = list1.size
    val size2 = list2.size
    val maxSize = max(size1, size2)

    val list3 = mutableListOf<Int>()

    var tenDigital = 0
    for (i in 0..maxSize) {
        if (i <= size1 - 1 && i <= size2 - 1) {
            val sum = list1[i] + list2[i] + tenDigital
            if (sum >= 10) {
                list3.add(sum % 10)
                tenDigital = 1
            } else {
                list3.add(sum)
                tenDigital = 0
            }
        } else if (i in (size1)..<size2) {
            val sum = list2[i] + tenDigital
            if (sum >= 10) {
                list3.add(sum % 10)
                tenDigital = 1
            } else {
                list3.add(sum)
                tenDigital = 0
            }

        } else if (i in (size2)..<size1) {
            val sum = list1[i] + tenDigital
            if (sum >= 10) {
                list3.add(sum % 10)
                tenDigital = 1
            } else {
                list3.add(sum)
                tenDigital = 0
            }
        } else if (i == maxSize) {
            if (tenDigital != 0) {
                list3.add(1)
                tenDigital = 0
            }
        }
    }

    return intArrayToListNode(list3.toIntArray())
}

//    var result = ListNode(0)
//    var str1 = node1.value.toString()
//    var str2 = node2.value.toString()
//    var next = node1.next
//    while (next != null) {
//        str1 += next.value
//        next = next.next
//    }
//    next = node2.next
//    while (next != null) {
//        str2 += next.value
//        next = next.next
//    }
//    val sum = (str1.toInt() + str2.toInt()).toString()
//
//    var chararray = sum.reversed().toCharArray()

class ListNode(var `val`: Int) {
    var next: ListNode? = null
}

/**
 * Example:
 * var li = ListNode(5)
 * var v = li.`val`
 * Definition for singly-linked list.
 * class ListNode(var `val`: Int) {
 *     var next: ListNode? = null
 * }
 */


fun intArrayToListNode(intArray: IntArray): ListNode {
    val list = mutableListOf<ListNode>()
    intArray.forEach { it ->
        val node = ListNode(it)
        list.add(node)
    }

    list.forEachIndexed { index, listNode ->
        if (index != list.size - 1) {
            listNode.next = list[index + 1]
        }
    }
    return list[0]
}

fun listNodeToIntArray(listNode: ListNode): IntArray {
    val list = mutableListOf<Int>()
    list.add(listNode.`val`)
    var next = listNode.next
    while (next != null) {
        list.add(next.`val`)
        next = next.next
    }
    return list.toIntArray()
}

fun arrayToListNode(charArray: CharArray) {
    var node = ListNode(charArray[0].toString().toInt())
    charArray.forEachIndexed { index, c ->
        if (index == 0) {
            return
        }
        var nodelist = ListNode(charArray[0].toString().toInt())
        node.next = nodelist
        node = nodelist
    }


}